﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace Daco.Web.Store
{
    public class CProductCategory : CBizObject, ICategory<int, CProductCategory>
    {
        #region Public properties
        private int _categoryID = -1;
        /// <summary>
        /// get the categoryID
        /// </summary>
        public int CategoryID { get { return _categoryID; } protected set { _categoryID = value; } }
        /// <summary>
        /// get or set category's title
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// get the encoded category's title
        /// </summary>
        public string EncodedTitle
        {
            get { return HttpContext.Current.Server.UrlEncode(Utils.CHelper.LatinToAscii(this.Title).Replace("\\", "").Replace("/", "")); }
        }
        /// <summary>
        /// get or set category's description
        /// </summary>
        public string Description { get; set; }

        private List<CProduct> _products = null;
        public List<CProduct> Products
        {
            get
            {
                if (_products == null)
                    _products = new List<CProduct>();
                return _products;
            }
        }

        private int _parentCategoryID = -1;
        private ICategory<int, CProductCategory> _parentCategory = null;
        public ICategory<int, CProductCategory> ParentCategory
        {
            get { return _parentCategory; }
            set { _parentCategory = value; }
        }
        private List<ICategory<int, CProductCategory>> _childCategories;
        public List<ICategory<int, CProductCategory>> ChildCategories
        {
            get
            {
                if (_childCategories == null)
                    _childCategories = new List<ICategory<int, CProductCategory>>();
                return _childCategories;
            }
            protected set
            {
                _childCategories = value;
            }
        }

        public CProductCategory OfType { get { return this; } }
        #endregion

        #region Public methods
        public bool Update()
        {
            return CProductCategory.UpdateCategory(this);
        }
        #endregion

        #region Public constructors
        public CProductCategory()
        {

        }

        public CProductCategory(int categoryID)
        {
            this.CategoryID = categoryID;
        }
        public CProductCategory(int categoryID, string title, string description)
        {
            CategoryID = categoryID;
            Title = title;
            Description = description;
        }

        public CProductCategory(int categoryID, int parentCategoryID, string parentCategoryTitle, string title, string description)
        {
            CategoryID = categoryID;
            Title = title;
            Description = description;
            _parentCategoryID = parentCategoryID;
            //if (parentCategoryID > 0) ParentCategory = new CProductCategory(parentCategoryID, parentCategoryTitle, string.Empty);
        }
        public CProductCategory(CProductCategory category)
        {
            //this.CategoryID = category.CategoryID;
            //if (category.ParentCategory == null)
            //{
            //    this.ParentCategory = new CProductCategory();
            //}
            //else
            //{
            //    this.ParentCategory = new CProductCategory(category.ParentCategory);
            //}
            //this.Title = category.Title;
            //this.Description = category.Description;
        }
        public CProductCategory Clone()
        {
            return new CProductCategory(this);
        }
        #endregion

        #region Public override methods
        public override bool Equals(object obj)
        {
            return ((CProductCategory)obj).CategoryID == this.CategoryID;
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override string ToString()
        {
            return this.CategoryID.ToString();
        }
        #endregion

        #region Public static methods
        public static CProductCategory GetCategory(int categoryID)
        {
            CProductCategory category = Providers.CStoreProvider.Instance.GetCategory(categoryID);
            if (category != null)
                category.ChildCategories.AddRange(GetCategoryTree(category.CategoryID));

            return category;
        }

        public List<ICategory<int, CProductCategory>> GetCategoryTree()
        {
            return CProductCategory.GetCategoryTree(this.CategoryID);
        }

        public static List<ICategory<int, CProductCategory>> GetCategoryTree(int parentCategoryID)
        {
            List<ICategory<int, CProductCategory>> categoryTree = new List<ICategory<int, CProductCategory>>();

            foreach (ICategory<int, CProductCategory> category in Providers.CStoreProvider.Instance.GetAllCategories(parentCategoryID))
            {
                if (category.OfType._parentCategoryID == -1)
                    categoryTree.Add(category);
                else
                {
                    ICategory<int, CProductCategory> parent = Find(categoryTree, new CProductCategory(category.OfType._parentCategoryID));
                    if (parent == null) throw new InvalidOperationException();

                    parent.ChildCategories.Add(category);
                    category.ParentCategory = parent;
                }
            }

            return categoryTree;
        }

        public static IEnumerable<CProductCategory> GetCategories()
        {
            return GetCategories(-1);
        }
        public static List<CProductCategory> GetCategories(int parentCategoryID)
        {
            List<CProductCategory> categoryList = new List<CProductCategory>(Providers.CStoreProvider.Instance.GetCategories(parentCategoryID));

            return categoryList;
        }

        //public static CTree CreateTree()
        //{
        //    return CreateTree(-1);
        //}

        //public static CTree CreateTree(int categoryID)
        //{
        //    List<CProductCategory> categories = CProductCategory.GetCategories(categoryID);
        //    CTree categoryTree = new CTree();

        //    foreach (CProductCategory category in categories)
        //    {
        //        CTreeNode node = new CTreeNode(category.Title, category.CategoryID.ToString());
        //        categoryTree.Nodes.AddNode(node);

        //        if (category.ChildCategories.Count > 0)
        //        {
        //            AddTreeNode(node, category.ChildCategories);
        //        }
        //    }

        //    return categoryTree;
        //}

        //private static void AddTreeNode(CTreeNode parent, IEnumerable<CProductCategory> categories)
        //{
        //    foreach (CProductCategory category in categories)
        //    {
        //        CTreeNode node = new CTreeNode(category.Title, category.CategoryID.ToString());
        //        parent.Nodes.AddNode(node);
        //        if (category.ChildCategories.Count > 0)
        //            AddTreeNode(node, category.ChildCategories);
        //    }
        //}

        //public static IEnumerable<CProductCategory> GetCategories(int parentCategoryID, bool enableRecursion)
        //{
        //    if (enableRecursion)
        //    {
        //        List<CProductCategory> categories = new List<CProductCategory>();

        //        foreach (CProductCategory category in Providers.CStoreProvider.Instance.GetAllCategories(parentCategoryID))
        //        {
        //            if (category.ParentCategory != null && categories.Contains(category.ParentCategory))
        //            {
        //                categories.Insert(categories.IndexOf(category.ParentCategory) + 1, category);
        //            }
        //            else categories.Add(category);
        //        }

        //        return categories;
        //    }
        //    else
        //        return Providers.CStoreProvider.Instance.GetCategories(parentCategoryID);
        //}
        public static CProductCategory CreateCategory(int parentCategoryID, string title, string description)
        {
            int categoryID = Providers.CStoreProvider.Instance.CreateCategory(parentCategoryID, title, description);

            if (categoryID > 0)
                return CProductCategory.GetCategory(categoryID);
            else
                return null;
        }
        //public static int CreateCategory(int categoryID, string title, string description)
        //{
        //    return 0;
        //}
        public static bool UpdateCategory(CProductCategory category)
        {
            bool success = false;
            //success = UpdateCategory(category.CategoryID, category.ParentCategory == null ? 0 : category.ParentCategory.CategoryID, category.Title, category.Description);
            success = Providers.CStoreProvider.Instance.UpdateCategory(
                    category.CategoryID,
                    category.ParentCategory == null ? 0 : category.ParentCategory.CategoryID,
                    category.Title,
                    category.Description
                );
            if (success)
            {
                // Clear cache
            }
            return success;
        }

        #endregion

        private static ICategory<int, CProductCategory> Find(List<ICategory<int, CProductCategory>> categoryList, ICategory<int, CProductCategory> match)
        {
            ICategory<int, CProductCategory> foundCategory = null;

            foreach (ICategory<int, CProductCategory> category in categoryList)
            {
                if (category.CategoryID == match.CategoryID)
                {
                    foundCategory = category;
                    break;
                }
                else if (category.ChildCategories != null && category.ChildCategories.Count > 0)
                {
                    if ((foundCategory = Find(category.ChildCategories, match)) != null)
                        break;
                }
            }

            return foundCategory;
        }

        public string GetFullTitle(string separator)
        {
            string key = "Daco_ProductCategory_GetFullTitle_" + this.CategoryID.ToString();
            string[] categoryTitles = null;

            if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
            {
                categoryTitles = (string[])CBizObject.Cache[key];
            }
            else
            {
                categoryTitles = Providers.CStoreProvider.Instance.GetFullProductCategoryTitle(this.CategoryID);
                CacheData(key, categoryTitles);
            }

            if (categoryTitles == null)
                return string.Empty;
            else
            {
                StringBuilder sb = new StringBuilder();
                for (int i = categoryTitles.Length - 1; i >= 0; i--)
                    sb.Append(categoryTitles[i]).Append(separator);
                if (sb.Length > separator.Length) sb.Remove(sb.Length - separator.Length, separator.Length);
                return sb.ToString();
            }
        }

        /// <summary>
        /// Cache the input data, if caching is enabled
        /// </summary>
        protected static void CacheData(string key, object data)
        {
            if (Config.CSiteConfig.Current.EnableCaching && data != null)
            {
                CBizObject.Cache.Insert(key, data, null,
                   DateTime.Now.AddSeconds(Config.CSiteConfig.Current.CacheDuration), TimeSpan.Zero);
            }
        }
    }
}
